After installing the Vivado and Vitis environments on Ubuntu, you can develop applications using Vitis on the Ubuntu system. Similar to Windows, you need to first create a platform project and then create the corresponding application project.
When we created the Petalinux project, we already imported the XSA file into Ubuntu. At this point, select this XSA file and choose Linux as the system: click finish.
Create an application project. This time we will only create one application project and organize different peripheral tests into modules. First, create an application project:
Click finish, and the application project is created.
The current GPIO configuration enables 2 MIO LEDs/2 EMIO LEDs, 2 MIO KEYs/2 EMIO KEYs, and one buzzer.
In the Linux system, GPIO can be conveniently controlled through the sysfs interface. Below is how to use sysfs to control GPIO on the Zynq-7020 platform.
Zynq-7020 GPIO is divided into:
MIO (Multiplexed I/O): 54 pins directly connected to the PS (Processing System)
EMIO (Extended MIO): GPIO extended through the PL (Programmable Logic)
First, you need to determine the number of the GPIO you want to control in the Linux system. The gpiochips number under /sys/class/gpio corresponds to the first GPIO and MIO0 number, which is generally 906.
xxxxxxxxxx# View GPIO device namescd /sys/class/gpiols# ls display result: export gpiochip906 unexport# This indicates the GPIO device name is gpiochip906, corresponding to starting number 906# There are 54 MIOs, so EMIO starts from 906+54=960GPIO number calculation formula:
MIO GPIO: MIO original number 0~53, corresponding to Linux number 906~959
EMIO GPIO: EMIO number starts from 54, corresponding to Linux number starting from 960
For example:
MIO11 corresponds to GPIO number 917
EMIO GPIO0 corresponds to GPIO number 960
Assuming you want to control EMIO0, you need to export this GPIO first.
xxxxxxxxxx# Export GPIO54echo 960 > /sys/class/gpio/exportSet GPIO to output or input mode:
xxxxxxxxxx# Set to output modeecho out > /sys/class/gpio/gpio960/direction# Or set to input modeecho in > /sys/class/gpio/gpio960/direction# Query pin directioncat /sys/class/gpio/gpio960/direction
Output mode (controlling LEDs, etc.):
xxxxxxxxxx# Output high levelecho 1 > /sys/class/gpio/gpio960/value# Output low levelecho 0 > /sys/class/gpio/gpio960/value
Input mode (reading buttons, etc.):
xxxxxxxxxx# Read GPIO valuecat /sys/class/gpio/gpio960/value
After use, you can unexport:
xxxxxxxxxxecho 960 > /sys/class/gpio/unexport
Right-click "src"->"new"->"Folder" to create GPIO and TEST folders:
Right-click "GPIO"->"new"->"File" to create corresponding .c/.h files; right-click "TEST"->"new"->"File" to create corresponding .c files; right-click "src"->"new"->"File" to create main.c/main.h.
After adding the corresponding code, the final project structure is as follows:
Open Vitis, click the following icon:
Select Linux Agent as default, and double-click to configure this Agent:
In the pop-up interface, enter the development board's IP address in the Host field, keep the port as default, no need to change:
After filling in, you can click Test Connection to test whether the connection is successful or failed. The following content indicates a successful connection:
Click ok to exit.
Because the default download path is the first partition of the SD card, and the default first partition is used to store kernel images, BOOT.BIN, and other information. So create a new folder app under /home/root and download the compiled .elf file to this folder.
You can directly click the icon in the upper left corner to compile the code, or click "build project" as before to compile:
If this type of error occurs
The corresponding solution is to add the header file path to the search path.
Right-click the project, select "C/C++ Build Settings":
After "Add":
After adding, the page:
Now it can compile successfully.
During Debug, Vitis will download the code to the development board's /home/root/app directory to run. At this point, you can use Vitis for single-step debugging or breakpoint debugging.
// export GPIOvoid export_gpio(int pin) { char buffer[4]; int fd = open("/sys/class/gpio/export", O_WRONLY); if (fd < 0) { perror("Failed to open export"); exit(1); } snprintf(buffer, sizeof(buffer), "%d", pin); write(fd, buffer, strlen(buffer)); close(fd); usleep(100000); // wait sysfs node build}
// set GPIO directionvoid set_direction(int pin, const char* direction) { char path[64]; snprintf(path, sizeof(path), "/sys/class/gpio/gpio%d/direction", pin); int fd = open(path, O_WRONLY); if (fd < 0) { perror("Failed to open direction"); exit(1); } write(fd, direction, strlen(direction)); close(fd);}
// write GPIOvoid write_gpio(int pin, int value) { char path[64]; char val = value ? '1' : '0'; snprintf(path, sizeof(path), "/sys/class/gpio/gpio%d/value", pin); int fd = open(path, O_WRONLY); if (fd < 0) { perror("Failed to open value for writing"); exit(1); } write(fd, &val, 1); close(fd);}
// read GPIOint read_gpio(int pin) { char path[64]; char val; snprintf(path, sizeof(path), "/sys/class/gpio/gpio%d/value", pin); int fd = open(path, O_RDONLY); if (fd < 0) { perror("Failed to open value for reading"); exit(1); } read(fd, &val, 1); close(fd); return (val == '1') ? 1 : 0;}